
#ifndef SW_CRC_H__
#define SW_CRC_H__

#include "stdint.h"
#include "stdlib.h"

#define CRC_TRUE  1U
#define CRC_FALSE 0U

/********************************************************************
 * @brief    传递生成CRC数据表相关信息
 * @param u8width 	【CRC 的宽度（以位为单位）】
 * @param u32poly 	【CRC 的生成多项式】
 * @param u32init 	【CRC 的初始值】
 * @param u8refin 	【指示数据是否在输入时被反转（LSB 优先）】
 * @param u8refout 	【指示 CRC 值是否在输出时被反转】
 * @param u32xorout 【与最终 CRC 值异或的值】
 ********************************************************************/
typedef struct
{
	uint8_t 	u8width;
	uint32_t 	u32poly;
	uint32_t 	u32init;
	uint8_t 	u8refin;
	uint8_t 	u8refout;
	uint32_t 	u32xorout;
} CRC_INFO;

/********************************************************
 * @brief	计算CRC所使用的各参数
 * @param pu8Table 		【CRC的数据表】
 * @param u8InitVal 	【CRC的初始值】
 * @param u8RefIn 		【指示数据是否在输入时被反转（LSB 优先）】
 * @param u8RefOut 		【指示CRC值是否在输出时被反转】
 * @param u8XorOut 		【与最终CRC值异或的值】
 ********************************************************/
typedef struct
{
    const uint8_t *pu8Table;
    uint8_t u8InitVal;
    uint8_t u8RefIn;
    uint8_t u8RefOut;
    uint8_t u8XorOut;
}SW_CRC8_st_t;

typedef struct
{
    const uint16_t *pu16Table;
    uint16_t u16InitVal;
    uint8_t  u8RefIn;
    uint8_t  u8RefOut;
    uint16_t u16XorOut;
}SW_CRC16_st_t;

typedef struct
{
    const uint32_t *pu32Table;
    uint32_t u32InitVal;
    uint8_t  u8RefIn;
    uint8_t  u8RefOut;
    uint32_t u32XorOut;
}SW_CRC32_st_t;



/* Software CRC type enable */
#define   SW_CRC8_ENABLE					(1U)
#define   SW_CRC8_ITU_ENABLE				(1U)
#define   SW_CRC8_ROHC_ENABLE				(1U)
#define   SW_CRC8_MAXIM_ENABLE				(1U)
#define   SW_CRC16_IBM_ENABLE				(1U)
#define   SW_CRC16_MAXIM_ENABLE				(1U)
#define   SW_CRC16_USB_ENABLE				(1U)
#define   SW_CRC16_MODBUS_ENABLE			(1U)
#define   SW_CRC16_CCITT_ENABLE				(1U)
#define   SW_CRC16_CCITT_FALSE_ENABLE		(1U)
#define   SW_CRC16_X25_ENABLE				(1U)
#define   SW_CRC16_XMODEM_ENABLE			(1U)
#define   SW_CRC16_DNP_ENABLE				(1U)
#define   SW_CRC32_ENABLE					(1U)
#define   SW_CRC32_MPEG_2_ENABLE			(1U)



#if SW_CRC8_ENABLE
    extern const SW_CRC8_st_t g_stSWCRC8;
    #define SW_CRC8                         (( SW_CRC8_st_t* )&g_stSWCRC8)
#else
    #define SW_CRC8                         (NULL)
#endif

#if SW_CRC8_ITU_ENABLE
    extern const SW_CRC8_st_t g_stSWCRC8_ITU;
    #define SW_CRC8_ITU                     (( SW_CRC8_st_t* )&g_stSWCRC8_ITU)
#else
    #define SW_CRC8_ITU                     (NULL)
#endif

#if SW_CRC8_ROHC_ENABLE
    extern const SW_CRC8_st_t g_stSWCRC8_ROHC;
    #define SW_CRC8_ROHC                    (( SW_CRC8_st_t* )&g_stSWCRC8_ROHC)
#else
    #define SW_CRC8_ROHC                    (NULL)
#endif

#if SW_CRC8_MAXIM_ENABLE
    extern const SW_CRC8_st_t g_stSWCRC8_MAXIM;
    #define SW_CRC8_MAXIM                   (( SW_CRC8_st_t* )&g_stSWCRC8_MAXIM)
#else
    #define SW_CRC8_MAXIM                   (NULL)
#endif

#if SW_CRC16_IBM_ENABLE
    extern const SW_CRC16_st_t g_stSWCRC16_IBM;
    #define SW_CRC16_IBM                    (( SW_CRC16_st_t* )&g_stSWCRC16_IBM)
#else
    #define SW_CRC16_IBM                    (NULL)
#endif

#if SW_CRC16_MAXIM_ENABLE
    extern const SW_CRC16_st_t g_stSWCRC16_MAXIM;
    #define SW_CRC16_MAXIM                  (( SW_CRC16_st_t* )&g_stSWCRC16_MAXIM)
#else
    #define SW_CRC16_MAXIM                  (NULL)
#endif

#if SW_CRC16_USB_ENABLE
    extern const SW_CRC16_st_t g_stSWCRC16_USB;
    #define SW_CRC16_USB                    (( SW_CRC16_st_t* )&g_stSWCRC16_USB)
#else
    #define SW_CRC16_USB                    (NULL)
#endif

#if SW_CRC16_MODBUS_ENABLE
    extern const SW_CRC16_st_t g_stSWCRC16_MODBUS;
    #define SW_CRC16_MODBUS                 (( SW_CRC16_st_t* )&g_stSWCRC16_MODBUS)
#else
    #define SW_CRC16_MODBUS                 (NULL)
#endif

#if SW_CRC16_CCITT_ENABLE
    extern const SW_CRC16_st_t g_stSWCRC16_CCITT;
    #define SW_CRC16_CCITT                  (( SW_CRC16_st_t* )&g_stSWCRC16_CCITT)
#else
    #define SW_CRC16_CCITT                  (NULL)
#endif

#if SW_CRC16_X25_ENABLE
    extern const SW_CRC16_st_t g_stSWCRC16_X25;
    #define SW_CRC16_X25                    (( SW_CRC16_st_t* )&g_stSWCRC16_X25)
#else
    #define SW_CRC16_X25                    (NULL)
#endif

#if SW_CRC16_CCITT_FALSE_ENABLE
    extern const SW_CRC16_st_t g_stSWCRC16_CCITT_FALSE;
    #define SW_CRC16_CCITT_FALSE            (( SW_CRC16_st_t* )&g_stSWCRC16_CCITT_FALSE)
#else
    #define SW_CRC16_CCITT_FALSE            (NULL)
#endif

#if SW_CRC16_XMODEM_ENABLE
    extern const SW_CRC16_st_t g_stSWCRC16_XMODEM;
    #define SW_CRC16_XMODEM                 (( SW_CRC16_st_t* )&g_stSWCRC16_XMODEM)
#else
    #define SW_CRC16_XMODEM                 (NULL)
#endif

#if SW_CRC16_DNP_ENABLE
    extern const SW_CRC16_st_t g_stSWCRC16_DNP;
    #define SW_CRC16_DNP                    (( SW_CRC16_st_t* )&g_stSWCRC16_DNP)
#else
    #define SW_CRC16_DNP                    (NULL)
#endif

#if SW_CRC32_ENABLE
    extern const SW_CRC32_st_t g_stSWCRC32;
    #define SW_CRC32                        (( SW_CRC32_st_t* )&g_stSWCRC32)
#else
    #define SW_CRC32                        (NULL)
#endif

#if SW_CRC32_MPEG_2_ENABLE
    extern const SW_CRC32_st_t g_stSWCRC32_MPEG_2;
    #define SW_CRC32_MPEG_2                 (( SW_CRC32_st_t* )&g_stSWCRC32_MPEG_2)
#else
    #define SW_CRC32_MPEG_2                 (NULL)
#endif



/**输入相关信息返回CRC数据表 见 CRC_INFO */
extern void crc_u32table_init(CRC_INFO* info, uint32_t* u32table);

/**********************************************************
 * @brief     用于计算CRC值
 * @param[in] stType 	【计算CRC所使用参数结构体】
 * @param[in] u8Data 	【所需校验的数据】
 * @param[in] u32Len 	【数据长度（以字节为单位）】
 * @return    uint8_t  【返回CRC值】
 * 
 * @warning   None
 * @since     1.0.0
 **********************************************************/
extern uint8_t  SW_CRC8_Calculate(SW_CRC8_st_t* stType, uint8_t u8Data[], uint32_t u32Len);
extern uint8_t  SW_CRC8_Calculate_Default(uint8_t u8Data[], uint32_t u32Len);

extern uint16_t SW_CRC16_Calculate(SW_CRC16_st_t* stType, uint8_t u8Data[], uint32_t u32Len);
extern uint16_t SW_CRC16_Calculate_Default(uint8_t u8Data[], uint32_t u32Len);

extern uint32_t SW_CRC32_Calculate(SW_CRC32_st_t* stType, uint8_t u8Data[], uint32_t u32Len);
extern uint32_t SW_CRC32_Calculate_Default(uint8_t u8Data[], uint32_t u32Len);

uint32_t reflected(uint32_t u32input, uint8_t bits);






#endif /* SW_CRC_H__ */
